
//sha1加密工具
let _sha1 = function () {

  "use strict";

  let __b64pad = "";
  let __hex_case = 0;
  let __char_bit = 8;

  let __safe_add = function (x, y) {
    let lsw = (x & 0xFFFF) + (y & 0xFFFF);
    let msw = (x >> 16) + (y >> 16) + (lsw >> 16);
    return msw << 16 | lsw & 0xFFFF;
  };

  let __rol = function (num, cnt) {return num << cnt | num >>> 32 - cnt;};

  let __sha1_ft = function (t, b, c, d) {
    if (t < 20) return b & c | ~b & d;
    if (t < 40) return b ^ c ^ d;
    if (t < 60) return b & c | b & d | c & d;
    return b ^ c ^ d;
  };

  let __sha1_kt = function (t) {
    return t < 20 ? 1518500249 : t < 40 ? 1859775393 : t < 60 ? -1894007588 : -899497514;
  };

  let __str_to_binary = function (str) {
    let bin = Array();
    let mask = (1 << __char_bit) - 1;
    for (let i = 0; i < str.length * __char_bit; i += __char_bit)
    bin[i >> 5] |= (str.charCodeAt(i / __char_bit) & mask) << 24 - i % 32;
    return bin;
  };
  let __binary_to_str = function (bin) {
    let str = "";
    let mask = (1 << __char_bit) - 1;
    for (let i = 0; i < bin.length * 32; i += __char_bit)
    str += String.fromCharCode(bin[i >> 5] >>> 24 - i % 32 & mask);
    return str;
  };

  let __binary_to_hex = function (binary) {
    let hex_tab = __hex_case ? "0123456789ABCDEF" : "0123456789abcdef";
    let str = "";
    for (let i = 0; i < binary.length * 4; i++)
    {
      str += hex_tab.charAt(binary[i >> 2] >> (3 - i % 4) * 8 + 4 & 0xF) + hex_tab.charAt(binary[i >> 2] >> (3 - i % 4) * 8 & 0xF);
    }
    return str;
  };

  let __binary_to_b64 = function (binary) {
    let tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    let str = "";
    for (let i = 0; i < binary.length * 4; i += 3)
    {
      let triplet = (binary[i >> 2] >> 8 * (3 - i % 4) & 0xFF) << 16 | (binary[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4) & 0xFF) << 8 | binary[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4) & 0xFF;
      for (let j = 0; j < 4; j++)
      {
        if (i * 8 + j * 6 > binary.length * 32) str += __b64pad;else
        str += tab.charAt(triplet >> 6 * (3 - j) & 0x3F);
      }
    }
    return str;
  };

  let __core_sha1 = function (x, len) {
    x[len >> 5] |= 0x80 << 24 - len % 32;
    x[(len + 64 >> 9 << 4) + 15] = len;

    let w = Array(80);
    let a = 1732584193;
    let b = -271733879;
    let c = -1732584194;
    let d = 271733878;
    let e = -1009589776;

    for (let i = 0; i < x.length; i += 16)
    {
      let olda = a;
      let oldb = b;
      let oldc = c;
      let oldd = d;
      let olde = e;

      for (let j = 0; j < 80; j++)
      {
        if (j < 16) w[j] = x[i + j];else
        w[j] = __rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
        let t = __safe_add(__safe_add(__rol(a, 5), __sha1_ft(j, b, c, d)), __safe_add(__safe_add(e, w[j]), __sha1_kt(j)));
        e = d;
        d = c;
        c = __rol(b, 30);
        b = a;
        a = t;
      }

      a = __safe_add(a, olda);
      b = __safe_add(b, oldb);
      c = __safe_add(c, oldc);
      d = __safe_add(d, oldd);
      e = __safe_add(e, olde);
    }
    return Array(a, b, c, d, e);
  };

  let __core_hmac_sha1 = function (key, data) {
    let bkey = __str_to_binary(key);
    if (bkey.length > 16) bkey = __core_sha1(bkey, key.length * __char_bit);

    let ipad = Array(16),
      opad = Array(16);
    for (let i = 0; i < 16; i++)
    {
      ipad[i] = bkey[i] ^ 0x36363636;
      opad[i] = bkey[i] ^ 0x5C5C5C5C;
    }

    let hash = __core_sha1(ipad.concat(__str_to_binary(data)), 512 + data.length * __char_bit);
    return __core_sha1(opad.concat(hash), 512 + 160);
  };

  //实例
  let __instance = null;
  //接口类
  let Class = function () {};

  //实现单例
  let GetInstance = function () {
    if (__instance == null)
    {
      __instance = new Class();
    }
    return __instance;
  };

  //对外接口，接受字符串参数并返回十六进制或base-64编码的字符串
  Class.prototype._hex_sha1 = function (s) {return __binary_to_hex(__core_sha1(__str_to_binary(s), s.length * __char_bit));};
  Class.prototype._b64_sha1 = function (s) {return __binary_to_b64(__core_sha1(__str_to_binary(s), s.length * __char_bit));};
  Class.prototype._str_sha1 = function (s) {return __binary_to_str(__core_sha1(__str_to_binary(s), s.length * __char_bit));};
  Class.prototype._hex_hmac_sha1 = function (key, data) {return __binary_to_hex(__core_hmac_sha1(key, data));};
  Class.prototype._b64_hmac_sha1 = function (key, data) {return __binary_to_b64(__core_hmac_sha1(key, data));};
  Class.prototype._str_hmac_sha1 = function (key, data) {return __binary_to_str(__core_hmac_sha1(key, data));};

  //执行一个简单的自检，看看虚拟机是否正常工作
  Class.prototype._sha1_vm_test = function () {return this._hex_sha1("abc") === "a9993e364706816aba3e25717850c26c9cd0d89d";};

  //返回
  return GetInstance();

}();

//导出
export default _sha1;